package com.hp.TrimClient;


import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

import org.apache.http.client.ClientProtocolException;

import com.hp.TrimClient.Models.RecordDownload;


public class TrimClient {
	
	private TrimHttp trimHttp;
	private TrimJson trimJson;
	
	public TrimClient() {
		
	}
	
	
	public TrimClient(String baseUri, org.apache.http.auth.Credentials credentials, Boolean ignoreSSLErrors) throws URISyntaxException, KeyManagementException {
		trimHttp = new TrimHttp(baseUri, credentials, ignoreSSLErrors);
		trimJson = new TrimJson();
	}
	
	public TrimClient(String baseUri, org.apache.http.auth.Credentials credentials) throws URISyntaxException, KeyManagementException {

		
		this(baseUri, credentials, false);
	}
	
	public String getDocument(RecordDownload request, String downloadPath) throws ClientProtocolException, IOException, IllegalArgumentException, URISyntaxException, IllegalAccessException, InvocationTargetException {
	
		return trimHttp.downloadFile(SimpleSerializer.objectToUrl(request), downloadPath);
	}

	/*public void setDocument(UploadSpecification uploadSpec) throws ClientProtocolException, IOException {		
	
		 trimHttp.uploadFile(uploadSpec);		

	}*/

	private Class<?> getResponseClass(Object request) throws Exception {
		Annotation restPath = request.getClass().getAnnotation(RestPath.class);
		if(restPath instanceof RestPath){
		
			return Class.forName(((RestPath)restPath).responseClass());
		} else {
			throw new Exception(Messages.getString("msg")); //$NON-NLS-1$
		}
	}

	public void post(Object request) throws Exception {
		//TODO: make sure to throw an Exception here if an error has occurred!!!
		trimHttp.doPost(SimpleSerializer.objectToUrl(request), request);
		
	}
	
	private void setFieldsOnObject(Class<?> thisClass, Object loc, Object original) throws IllegalArgumentException, IllegalAccessException {
		Field[] fields = thisClass.getDeclaredFields();
		
		for (Field fld : fields) {
			fld.setAccessible(true);
			
			fld.set(original, fld.get(loc));
		}	
		
		if (thisClass.getSuperclass() != null) {
			setFieldsOnObject(thisClass.getSuperclass(), loc, original);
		}
	}
	
	public void postAndUpdate(Object request, File file) throws Exception {
		Class<?> classOfTResponse = getResponseClass(request);
		String json = trimHttp.doPost(SimpleSerializer.objectToUrl(request), request, file);
		Object response = trimJson.fromJson(json, classOfTResponse);
		
		Object updated = TrimMainObjectSearchResponse.class.cast(response).getResults().get(0);
		
		setFieldsOnObject(request.getClass(), updated, request);
		
		//return response;
	}
	
	public <TResponse> TResponse post(Returns<TResponse> request) throws Exception {
		Class<?> classOfTResponse = getResponseClass(request);
		String json = trimHttp.doPost(SimpleSerializer.objectToUrl(request), request);
		TResponse response = trimJson.fromJson(json, classOfTResponse);
		return response;
	}
	
	public <TResponse> TResponse postWithFile(Returns<TResponse> request, File file) throws Exception {
		Class<?> classOfTResponse = getResponseClass(request);
		String json = trimHttp.doPost(SimpleSerializer.objectToUrl(request), request, file);
		TResponse response = trimJson.fromJson(json, classOfTResponse);
		return response;
	
	}
	
	
	public <TResponse> TResponse get(Returns<TResponse> request) throws Exception {

		Class<?> classOfTResponse = getResponseClass(request);
			
		String json = trimHttp.doGet(SimpleSerializer.objectToUrl(request));
			
		TResponse response = trimJson.fromJson(json, classOfTResponse);
		
		if (response instanceof ServiceObject) {
			((ServiceObject)response).setTrimClient(this);
		}
		return response;

	}


}
